#include <buola/chart/cxyzchart.h>

#include <buola/image/cfont.h>
#include <buola/image/cgc.h>
#include <buola/utility/random.h>
#include <buola/gl.h>

#include <buola/chart/plots/cxyzplot.h>

namespace buola { namespace chart {

CXYZChart::CXYZChart()
    :   mXAxis(new C3DAxis(C3DAxis::AXIS_X)),
        mYAxis(new C3DAxis(C3DAxis::AXIS_Y)),
        mZAxis(new C3DAxis(C3DAxis::AXIS_Z)),
        mLegend(new CLegend),
        mXRot(110.0),
        mZRot(-40.0)
{
}

CXYZChart::~CXYZChart()
{
}

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
////////////////////////// Interface //////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

void CXYZChart::AddPlot(PXYZPlot pPlot)
{
    mPlots.push_back(pPlot);

    if(pPlot->GetName().empty())
    {
        pPlot->SetName(L"plot "+to_wstring(mPlots.size()));
    }
}

void CXYZChart::RemovePlot(PXYZPlot pPlot)
{
    mPlots.erase(std::find(mPlots.begin(),mPlots.end(),pPlot));
}

void CXYZChart::RemovePlots()
{
    mPlots.clear();
}

void CXYZChart::OnExpose(const gui::CExposeEvent &pE)
{
#if 0
    CXYZChartContext lC;
    lC.mChart=this;
    lC.mGC=pE.mGC;
    lC.mRect=CRect_d({0,0},Size());
    lC.mXAxis=mXAxis;
    lC.mYAxis=mYAxis;
    lC.mZAxis=mZAxis;
    lC.mLegend=mLegend;
    mLegend->ClearItems();

    //calculate minimum and maximum in each axis for all plots
    if(!mPlots.size())
    {
        lC.mMinX=0;
        lC.mMinPosX=0.1;
        lC.mMaxX=1;
        lC.mMinY=0;
        lC.mMinPosY=0.1;
        lC.mMaxY=1;
        lC.mMinZ=0;
        lC.mMinPosZ=0.1;
        lC.mMaxZ=1;
    }
    else
    {
        lC.mMinX=mPlots[0]->GetMinX();
        lC.mMinPosX=mPlots[0]->GetMinPosX();
        lC.mMaxX=mPlots[0]->GetMaxX();
        lC.mMinY=mPlots[0]->GetMinY();
        lC.mMinPosY=mPlots[0]->GetMinPosY();
        lC.mMaxY=mPlots[0]->GetMaxY();
        lC.mMinZ=mPlots[0]->GetMinZ();
        lC.mMinPosZ=mPlots[0]->GetMinPosZ();
        lC.mMaxZ=mPlots[0]->GetMaxZ();

        for(int i=1;i<mPlots.size();i++)
        {
            lC.mMinX=min(lC.mMinX,mPlots[i]->GetMinX());
            lC.mMinPosX=min(lC.mMinPosX,mPlots[i]->GetMinPosX());
            lC.mMaxX=max(lC.mMaxX,mPlots[i]->GetMaxX());
            lC.mMinY=min(lC.mMinY,mPlots[i]->GetMinY());
            lC.mMinPosY=min(lC.mMinPosY,mPlots[i]->GetMinPosY());
            lC.mMaxY=max(lC.mMaxY,mPlots[i]->GetMaxY());
            lC.mMinZ=min(lC.mMinZ,mPlots[i]->GetMinZ());
            lC.mMinPosZ=min(lC.mMinPosZ,mPlots[i]->GetMinPosZ());
            lC.mMaxZ=max(lC.mMaxZ,mPlots[i]->GetMaxZ());
        }
    }

    mXAxis->CalcLimits(lC.mMinX,lC.mMinPosX,lC.mMaxX);
    mYAxis->CalcLimits(lC.mMinY,lC.mMinPosY,lC.mMaxY);
    mZAxis->CalcLimits(lC.mMinZ,lC.mMinPosZ,lC.mMaxZ);

    GLfloat lAspect(Size().x/Size().y);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

//    if(lAspect<1.0f)
//        glOrtho(-1.5,1.5,-1.5/lAspect,1.5/lAspect,2.0,-2.0);
//    else
//        glOrtho(-1.5*lAspect,1.5*lAspect,-1.5,1.5,2.0,-2.0);

//    glMatrixMode(GL_MODELVIEW);
//    glLoadIdentity();

//    glRotatef(mXRot,-1.0f,0.0f,0.0f);
//    glRotatef(mZRot,0.0f,0.0f,1.0f);

    gl::clear_color(img::CColor(0.85,0.85,0.85));
//    glbColor(CColor(BLACK));
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    for(int i=0;i<mPlots.size();i++)
    {
        mPlots[i]->Draw(lC);
    }

    mZAxis->Draw(lC);
    mYAxis->Draw(lC);
    mXAxis->Draw(lC);

//  pGC->SetStockFont(L"text");
//  pGC->SetLineWidth(1.5);
//
//  if(GetStyleBit(LEGEND))
//      mLegend->Draw(lC);

    //storing data for interaction
    mDataRect=lC.mRect;
#endif
}

void CXYZChart::OnButtonDown(const gui::CMouseEvent &pE)
{
    mMousePos=pE.mPoint;
}

void CXYZChart::OnMouseMove(const gui::CMouseEvent &pE)
{
    double lNewXRot=mXRot+(pE.mPoint.y-mMousePos.y)/3.0;
    double lNewZRot=mZRot-(pE.mPoint.x-mMousePos.x)/3.0;
    mMousePos=pE.mPoint;

    if(lNewXRot>180.0)
        lNewXRot=180.0;
    else if(lNewXRot<0.0)
        lNewXRot=0.0;
    if(lNewZRot>180.0)
        lNewZRot-=360.0;
    else if(lNewZRot<-180.0)
        lNewZRot+=360.0;

    if(lNewZRot!=mZRot||lNewXRot!=mXRot)
    {
        mXRot=lNewXRot;
        mZRot=lNewZRot;
    }
}

PXYZPlot CXYZChart::GetPlotAt(const CPoint_d &pPos)
{
    return nullptr;
}

/*namespace chart*/ } /*namespace buola*/ }
